﻿using log4net;
using System.Collections.Generic;
using System;
using System.ComponentModel;
using System.Threading;
using RemoteData.core.queue;
using RemoteData.common.converter;
using System.Net.Sockets;


namespace RemoteData.core.Listener
{
    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    public enum ListeningState
    {
        [Description("监听中")]
        LISTENING = 0,
        [Description("未监听")]
        UNLISTENING,
    }
    public class ListenerManager
    {
        private static ILog logger = LogManager.GetLogger(typeof(ListenerManager));

        private readonly object locker = new object();

        public DeviceDataWorker dataWorker;

        private Thread thWorker = null;
        private bool stopFlag = true;

        public int port;

        private ListeningState status;

        public ListenerManager(int port)
        {
            this.port = port;
            dataWorker = new DeviceDataWorker(port);
        }

        public bool WaitListen(int millisecond)
        {
            bool rn = false;
            int conuts = 5;
            int sleepTm = millisecond / 5;
            int i = 0;
            while(i < conuts)
            {
                if(dataWorker.GetStatus() == ListeningState.LISTENING)
                {
                    rn = true;
                    break;
                }
                i++;
                Thread.Sleep(sleepTm);
            }
            return rn;
        }

        public int Start()
        {
            int rn = 0;
            stopFlag = false;
            while(!stopFlag)
            {
                lock (locker)
                {
                    if (this.dataWorker.IsStop())
                    {
                        this.dataWorker.StartReceiveSync();
                        WaitListen(1000);
                    }

                    if(dataWorker.GetStatus() == ListeningState.LISTENING)
                    {
                        status = ListeningState.LISTENING; 
                    }
                    else
                    {
                        status = ListeningState.UNLISTENING;
                        Thread.Sleep(1000);
                    }
                }
            }

            StopAllWorkers();
            return rn;
        }

        public int StartAsync()
        {
            int rn = 0;
            if (stopFlag)
            {
                thWorker = new Thread(new ThreadStart(() => Start()));
                if(thWorker != null)
                {
                    thWorker.Start();
                }
                else
                {
                    rn = -1;
                }
            }
            else
            {
                rn = -2;
            }
            return rn;
        }

        public void Stop()
        {
            stopFlag = true;
        }

        public void StopAllWorkers()
        {
            lock(locker)
            {
                dataWorker.DisListening();
                dataWorker.StopReceive();
                this.status = ListeningState.UNLISTENING ;
            }
        }

        public void Join()
        {
            dataWorker.Join();
        }

        public void Join(int milliseconds)
        {
            dataWorker.Join(milliseconds);
        }

        public ListeningState GetStatus()
        {
            lock( locker)
            {
                return status;
            }
        }

        public int Register(OPM_MsgWorker worker, QueueDataType key)
        {
            int rn = 0;
            List<QueueDataType> keyList = new List<QueueDataType>();
            keyList.Add(key);
            rn = Register(worker, keyList);

            return rn;
        }

        public int Register(OPM_MsgWorker worker, List<QueueDataType> keyList)
        {
            int rn = 0;
            int rn2 = 0;
            try
            {
                rn2 = dataWorker.msgDispatcher.Register(worker, keyList);
                if (rn2 != 0)
                {
                    logger.ErrorFormat("register失败");
                }
            }
            catch (Exception)
            {
                rn = -1;
            }
            return rn;
        }

        public void UnRegister(OPM_MsgWorker worker, QueueDataType key)
        {
            List<QueueDataType> keyList = new List<QueueDataType>();
            keyList.Add(key);
            UnRegister(worker, keyList);
            return;
        }
        public int UnRegister(OPM_MsgWorker worker, List<QueueDataType> keyList)
        {
            int rn = 0;
            try
            {
                lock (locker)
                {
                    dataWorker.msgDispatcher.UnRegister(worker, keyList);
                }
            }
            catch (Exception)
            {
                rn = -1;
            }
            return rn;
        }
    }
}
